﻿using System;
using System.Collections.Generic;

namespace ActionGraph.Core
{
    /// <summary>
    /// 图状态
    /// </summary>
    [Serializable]
    public enum GraphState
    {
        Running,
        Done
    }

    public class ActionGraphHost
    {
        public ActionGraph graph  { get; private set; }
        public GameEntity  entity { get; private set; }

        public GraphState state
        {
            get;
            private set;
        }

        private readonly List<ActionNode>    excuteNodeList = new List<ActionNode> ();
        private readonly HashSet<ActionNode> excuteNodeSet  = new HashSet<ActionNode> ();

        public void SetData (ActionGraph _graph, GameEntity _entity)
        {
            graph  = _graph;
            entity = _entity;

            if (graph.updateNode!=null)
            {
                excuteNodeList.Add (graph.updateNode);
                excuteNodeSet.Add (graph.updateNode);
            }

            if (graph.entryNode != null)
            {
                excuteNodeList.Add (graph.entryNode);
                excuteNodeSet.Add (graph.entryNode);
            }

            state = GraphState.Running;
        }

        public void RegisterExcute (ActionNode node)
        {
            if (excuteNodeSet.Contains (node))
            {
                return;
            }

            excuteNodeList.Add (node);
            excuteNodeSet.Add (node);
        }

        public void Excute ()
        {
            graph.graphHost = this;

            switch (state)
            {
                case GraphState.Running:
                    for (int i = excuteNodeList.Count - 1; i >= 0; i--)
                    {
                        var node = excuteNodeList[i];
                        if (node.HasExcuted || !node.Excute ())
                            continue;
                        excuteNodeSet.Remove (node);
                        excuteNodeList.RemoveAt (i);
                    }
                    if (excuteNodeList.Count==0)
                    {
                        state = GraphState.Done;
                    }
                    else
                    {
                        foreach (var actionNode in excuteNodeList)
                        {
                            actionNode.HasExcuted = false;
                        }
                    }
                    break;
                case GraphState.Done:
                    break;
            }
            graph.graphHost = null;
        }
    }
}